/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package kleinberg;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Objects;
import java.util.logging.Level;
import java.util.logging.Logger;
//import static kleinberg.Kleinberg.dates;

/**
 *
 * @author veena
 */
public class SingleStream {
    double gamma=1;
    double gammalogn=0;
    double s=2;//scaling parameter
    double n=0;//length of gaps
    double T=0;//total of all gaps
    double g=0;//n/T
    double min=0;//min of gaps
    double kstates=0;//no. of states reqd for optimal state transition
    ArrayList<Double> alpha=new ArrayList<Double>();
    ArrayList<Integer> gaps=new ArrayList<Integer>();
    ArrayList<Double> cost=new ArrayList<Double>();
        ArrayList<Double> c=new ArrayList<Double>();
        ArrayList<Double> costprime=new ArrayList<Double>();
        String dfile="/home/veena/veena/f14/660/TG/obamacare/mitt2012/file2";
        ArrayList<Double> tmp=new ArrayList<Double>();
        
        ArrayList<ArrayList<Double>> q;
        ArrayList<ArrayList<Double>> qprime;
    public SingleStream(){
       
    }
    public int[] readminutes(){
        BufferedReader buff=null;
        int[] offs=null;
        try {
        
        buff = new BufferedReader(new FileReader((dfile)));
        String s=null;String[] spl=null;
        int minutes=0;
        ArrayList<Integer> vals=new ArrayList<>();
        try {
            while((s=buff.readLine())!=null){
                spl=s.split("-");
                if(!spl[0].equals("") | !spl[0].isEmpty()){
                minutes=Integer.valueOf(spl[0].trim());
                vals.add(minutes);
//                System.out.println(minutes+" "+spl[1]);
                }
                
            }
            buff.close();
            offs=new int[vals.size()];
            for(int i=0;i<vals.size();i++){
                
                offs[i]=vals.get(i);
            }
            System.out.println(offs);
            return offs;
        } catch (IOException ex) {
            Logger.getLogger(Kleinberg.class.getName()).log(Level.SEVERE, null, ex);
        }
    } catch (FileNotFoundException ex) {
        Logger.getLogger(Kleinberg.class.getName()).log(Level.SEVERE, null, ex);
    }finally{
            try {
                buff.close();
            } catch (IOException ex) {
                Logger.getLogger(SingleStream.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return null;
    }
    public void preprocessing(){
        SingleStream sst=new SingleStream();
        double val=0,term1=0,term2=0,temp=0,tau=0.0,d1=0.0,d2=0.0;
        //take the inputs and process them
        int diff=0,st=0,ed=0,minindex=0;
                q = new ArrayList<ArrayList<Double>>();
                ArrayList<Double> tem=new ArrayList<Double>();
        qprime = new ArrayList<ArrayList<Double>>();
        ArrayList<String> bursts=new ArrayList<String>();
        ArrayList<Integer> bur=new ArrayList<Integer>();
        String[] spl1=null,spl2=null;
        String s1="",s2="",s3="";
        boolean condition=false;
        //read in offset values!
        
//        cost = new int[][];
//        int[] offsets={0,100,200,300,400,410,415,420,425,430,435,440,445,450,451,453,455,457,459,461,463,465,467,469,480,485,490,495,500,505,510,515,520,525,530,535,540,545,550,555,560,565,570,575,580,585,590,595,600,700,710,715,720,725,730,735,740,745,750,755,760,765,770,775,780,785,790,795,800,900,1000};
        int[] offsets=null; 
        //read offsets here 
        offsets=readminutes();
//        //find unique--not reqd diff ids with same tweet time
//        for(int i=0;i<offsets.length;i++){
//            if(!bur.contains(offsets[i])){
//            bur.add(offsets[i]);
//            }else
//                System.err.print(offsets[i]+"-");
//        }
//        offsets=null;
//        offsets=new int[bur.size()];
//        for(int i=0;i<bur.size();i++){
//            offsets[i]=bur.get(i);
//            
//        }
        
                //calculate gaps, n and T here
       
        //check offsets
//        for(int i=0;i<offsets.length;i++){
//            System.out.println(offsets[i]);
//        }
        //generate gaps now 
        for(int i=0;i<offsets.length-1;i++){
            if((i+1)<offsets.length)
            st=offsets[i+1];
            
            ed=offsets[i];
                diff=st-ed;
                if(diff==0)
                    gaps.add(1);
                else
                gaps.add(diff );
                T+=diff;
        
        }
        //check gaps
//        for (Integer gap : gaps) {
//            System.out.println(gap);
//        }
        diff=0;
        n=gaps.size();
        g=T/n;
//        System.out.println(gaps+"=\n"+Collections.min(gaps));
        min=Double.valueOf(Collections.min(gaps));
        kstates=Math.ceil(1+sst.logOfBase(s, T)+sst.logOfBase(s, (1/min)));
        for(int i=0;i<kstates;i++){
            cost.add(Double.POSITIVE_INFINITY);
        }
        for(int i=0;i<kstates;i++){
            val=Math.pow(s, i)/g;
            alpha.add(val);
//            System.out.println(alpha.get(i));
        }
        gammalogn=gamma*Math.log(n);
        //intitialization
//        c.set(0 , 0.0);c.set((int) kstates, 100000.0);//cost of size k
        for(int i=0;i<kstates;i++){//q of size k*t
            q.add(new ArrayList<Double>());
//            q.get(i).set(i, 0);
            if(i==0)
            c.add(0.0);
            else
                c.add(Double.POSITIVE_INFINITY);
        }
        
        //DYP for cost func
        for(int t=0;t<n;t++){
            //init inside
            qprime=new ArrayList<>();
            costprime=new ArrayList<>();

        for(int i=0;i<kstates;i++){
            qprime.add(new ArrayList<Double>());
            for(int ii=0;ii<n;ii++){ 
                qprime.get(i).add(0.0);
            }
        }//init qprime 
         
          
      //end init
            for(int j=0;j<kstates;j++){
                term1=alpha.get(j)*gaps.get(t)-Math.log(alpha.get(j));
                for(int l=0;l<kstates;l++){
                    //called cost
                    if(j>l){
                        tau=(j-l)*gammalogn;
                    }else{
                        tau=0.0;
                    }
                    double tmp_=tau+c.get(l);
                    if(tmp_>=0){
                        cost.set(l,tmp_);
                    }else
                     cost.set(l,Double.POSITIVE_INFINITY);
                }
                temp=Collections.min(cost);
//               System.out.print(cost+"#"+minindex+"@"+t+"$"+j);System.out.println();
                minindex=(cost.indexOf(temp));
                double add=cost.get(minindex)+term1;
                costprime.add(add);
                
                if(t>0){
                    tem=q.get(minindex);
//                    System.out.println(q.get(minindex));
                    for(int kk=0;kk<t;kk++){
//                        System.out.println(q.get(j).get(minindex));
                        qprime.get(j).set(kk, tem.get(kk));
                    }
                    
                }
                
//                System.out.println(Double.valueOf(String.valueOf(j)));
                qprime.get(j).set(t,Double.valueOf(String.valueOf(j+1)));
//                
                /*if(t>0){
                    for(int i=0;i<t;i++){
                        
                     qprime.get(j).set(i,q.get(minindex).get(minindex));
                    }
//                    System.out.println("hey!");
                    qprime.get(j).set(t,q.get(j).get(minindex));
                }else
                qprime.get(j).set(t,Double.valueOf(String.valueOf(j)));*/
                
            }
            c=(costprime);
            q=(qprime);
//            for(int kk=0;kk<n;kk++){
//                for(int jj=0;jj<kstates;jj++){
//                    System.out.print(q.get(jj).get(kk)+"=");
//                }
//            }
        }
//        for(int i=0;i<q.size();i++){
//            for(int t=0;t<n;t++){
//                System.out.print(q.get(i).get(t)+":");
//            }
//            System.out.println();
//        }
        //printing the cost
        //pick up the row from q with minimum cost
                for(int i=0;i<c.size();i++){
                    System.out.println(c.get(i));
                }
      //find the index of minimum cost
                temp=Collections.min(cost);
                minindex=cost.indexOf(temp);
                tmp=q.get(minindex);
//                for(int i=0;i<tmp.size();i++){
//                    for(int i=0;i<offsets.length;i++){
//                        System.out.print(offsets[i]+"-"+i+";");
//                    }
                    System.out.println(tmp);
//                    for(int i=0;i<tmp.size();i++){
//                    System.out.print(tmp.get(i)+"-"+i+";");
//                    }
//                }
                //find how many levels it goes to how many states it changes
//                c.clear();
//                for(int i=0;i<tmp.size();i++){
//                    if(!c.contains(tmp.get(i))){
//                        c.add(tmp.get(i));
//                        
//                    }
//                }
                
        //to find levels and plot the bursts against it find the offset level where value of j is >=j
                for(int i=0;i<tmp.size();i++){
                    if(i==0){
                        s1=String.valueOf(1.0)+":"+offsets[i]+":";
                        bursts.add(s1);
                    }else{
                    //nested substructure of bursts
                        d1=tmp.get(i);
//                        System.out.println(d1);
                        if(i+1<tmp.size()-1)
                            d2=tmp.get(i+1);
//                        System.out.println(d2);
                        if(d2>d1){
    //                        
                            s2=String.valueOf(d2)+":"+offsets[i+1]+":";
//                            System.out.println(d2+"-"+offsets[i+1]);
                            bursts.add(s2);
                        }else if(d2<d1){
                            //ca be new level beginning here other than the ones present
                            //check if level not already present then add or else 
                            //if exists prev level continuing
                            for(int h=0;h<bursts.size();h++){
                                spl1=bursts.get(h).replace("\"", "").split(":");
                                if(spl1.length<3){
                                    if(Objects.equals(Double.valueOf(spl1[0]), d2)){
                                        condition=true;
                                        break;
                                    }
                                }
                            }
                            spl1=null;
                           if(condition){
                            //OR...
                        //level decreased-mark the end here of prev open 
                            //check if end is already appended or else append it
                            for(int h=0;h<bursts.size();h++){
                                spl1=bursts.get(h).split(":");
                                if(spl1.length<3){
                                    if(d2>Double.valueOf(spl1[0])){
                                        //not end of found val

                                    }else if(String.valueOf(d2).trim().equals(String.valueOf(spl1[0].trim()))){
                                    //not end of current val still continuing

                                    }else {
                                        s3=bursts.get(h);
                                        if(i+1<tmp.size()-1)
                                        s3+=offsets[i+1];
                                        bursts.set(h, s3);
//                                        System.out.println(h+"-"+s3);
                                        
                                        }
                                }
                            }
                        }else{
                               //anther level not in list added
                               s2=String.valueOf(d2)+":"+offsets[i+1]+":";
//                            System.out.println(d2+"-"+offsets[i+1]);
                                bursts.add(s2);
                               //close levels greater than this
                                for(int h=0;h<bursts.size();h++){
                                spl1=bursts.get(h).split(":");
                                    if(spl1.length<3){
                                        if(d2<Double.valueOf(spl1[0])){
                                        //close events greater than this
                                            s3=bursts.get(h);
                                        if(i+1<tmp.size()-1)
                                        s3+=offsets[i+1];
                                        bursts.set(h, s3);
//                                        System.out.println(h+"-"+s3);
                                    }


                                    }
                                }
                           }
                            condition=false;
                            }//else its same state
                            spl1=null;condition=false;
                            if(i==tmp.size()-1){
                                s1=bursts.get(0);
                                s1+=offsets[offsets.length-1];
                                
                                bursts.set(0, s1);
                            }
                    }
            }
               for(int i=0;i<bursts.size();i++){
                   spl1=bursts.get(0).split(":");
                   s3=spl1[2].trim();
                   spl1=bursts.get(i).split(":");
                   if(spl1.length<3){
                   //fill it up with missing last entry
                       s2=bursts.get(i);
                       s2+=s3;
                       bursts.set(i, s2);
                    }
                   System.out.println(bursts.get(i));
               }  
    }
    
private double logOfBase(double base, double num) {
    double val=0.0;
    val=Math.log10(num) / Math.log10(base);
    return val;
}

  
}
